<script lang="ts" setup>
import { eolink, R } from '@/api'
import store from '@/store'
import { ApiRequestType, ApiStatus, StatusCode } from '@/utils/eolink'
import { message } from 'ant-design-vue'
import _ from 'lodash'
import { ref, watchPostEffect } from 'vue'
import { useLoadMore } from 'vue-request'
import runtime, {
  CFG,
  getFileDocs,
  getFileImports,
  ws_cfg,
  yc_cfg_ts,
} from './runtime'

const $props = defineProps<{
  /** ws - 使用万视系统预设, yc - 使用云仓系统预设  */
  platform?: 'ws' | 'yc'
}>()

const ns = 'PageEolinkList'
const getItem = (key: string, defaultVal = '') =>
  localStorage.getItem(ns + key) || defaultVal
const setItem = (key: string, val = '') => localStorage.setItem(ns + key, val)

const isLoadAllKey = 'isLoadAll'
const isLoadAllRef = ref(JSON.parse(getItem(isLoadAllKey, 'true')))
const inputValKey = 'inputVal'
const inputValRef = ref(getItem(inputValKey, ''))
const textareaValKey = 'textareaValRef'
const textareaValRef = ref(getItem(textareaValKey, ''))
/** 支持选择批量 */
const selectedIds = ref(new Set<string>())

watchPostEffect(() => {
  setItem(isLoadAllKey, JSON.stringify(isLoadAllRef.value))
  setItem(inputValKey, inputValRef.value)
  setItem(textareaValKey, textareaValRef.value)
})

const { data, loading, reload, reloading } = useLoadMore(
  async function service(params: any) {
    if ($props.platform == 'ws') {
      // 万视 - eolink 文档 shareCode
      await store.dispatch(
        'eolink/getShareId',
        import.meta.env.VITE_EOLINK_SHARE_CODE_WS
      )
    } else if ($props.platform == 'yc') {
      // 云仓 - eolink 文档 shareCode
      await store.dispatch(
        'eolink/getShareId',
        import.meta.env.VITE_EOLINK_SHARE_CODE_YC
      )
    }
    /** 是否输入url直接输入列表链接 */
    const isKeywordURL =
      !!inputValRef.value && /^https?:\/\//.test(_.trim(inputValRef.value))
    const urlParms = isKeywordURL
      ? Object.fromEntries(
          new URLSearchParams(
            new URL(_.trim(inputValRef.value)).search.replace(/^\?/, '')
          )
        )
      : {}
    const _params: R.IParams<(typeof eolink)['searchApi']> = isKeywordURL
      ? {
          ...urlParms,
          shareID: await store.dispatch('eolink/getShareId'),
          shareCode: store.getters.shareCode,
          shareToken: store.getters.shareToken,
          shareType: 'project',
          page: 1,
          pageSize: 1e6,
          orderBy: '4',
          asc: '1',
        }
      : {
          ...params,
          shareID: await store.dispatch('eolink/getShareId'),
          shareCode: store.getters.shareCode,
          shareToken: store.getters.shareToken,
          shareType: 'project',
          page: 1,
          pageSize: 1e6,
          keyword: inputValRef.value,
          tip: inputValRef.value,
          orderBy: '4',
          asc: '1',
        }
    if (urlParms.search) {
      _params.keyword = _params.tip = decodeURIComponent(
        _.replace(urlParms.search, /~/g, '%')
      )
    }
    const res = await (_params.keyword
      ? eolink.searchApi(_params)
      : eolink.getApiList(_params))
    return res.apiList
  },
  {
    async onError(err) {
      if (!('response' in err)) return
      switch ((err as any).response.data.statusCode) {
        case StatusCode.UNAUTHORIZED:
        case StatusCode.TOKEN_EXPIRE:
          message.warning('请求未授权，重新登录')
          await store.dispatch('eolink/login')
          message.success('获取token完成，请刷新')
          break
        default:
          break
      }
    },
  }
)
function getApiStatusMap(status: ApiStatus) {
  const res = {
    color: '#cccccc',
    text: `未知状态: ${status}`,
  }
  switch (status) {
    case ApiStatus.PUBLISHED:
      _.assign(res, { color: 'green', text: '已发布' })
      break
    case ApiStatus.DEPRECATED:
      _.assign(res, { color: 'red', text: '废弃' })
      break
    case ApiStatus.MAINTAIN:
      _.assign(res, { color: 'red', text: '维护' })
      break
    case ApiStatus.DESIGN:
      _.assign(res, { color: 'blue', text: '设计' })
      break
    case ApiStatus.DEV:
      _.assign(res, { color: 'blue', text: '开发' })
      break
    case ApiStatus.TODEV:
      _.assign(res, { color: 'blue', text: '对接' })
      break
    case ApiStatus.FINISH:
      _.assign(res, { color: 'green', text: '已完成' })
      break
    case ApiStatus.UNDEF:
      _.assign(res, { color: 'yellow', text: '待定' })
      break
  }
  return res
}

const isGenCoding = ref(false)
async function onGenCodeBtnClick(
  records: R.IResponse<(typeof eolink)['getApiList']>['apiList']
) {
  if (_.isEmpty(records)) return

  try {
    let heading = `${getFileDocs()}${getFileImports()}`
    let text: string | boolean
    textareaValRef.value = heading
    isGenCoding.value = true
    for (const record of records) {
      const res = await eolink.getApiInfo({
        apiID: `${record.apiID}`,
        groupID: `${record.groupID}`,
        shareCode: store.getters.shareCode,
        shareID: store.getters.shareID,
        shareToken: store.getters.shareToken,
        shareType: 'project',
      })

      let fn: { (arg: CFG): boolean | string } | undefined = void 0
      if ($props.platform == 'ws') {
        fn = ws_cfg
      } else if ($props.platform == 'yc') {
        fn = yc_cfg_ts
      }
      text = runtime(res.apiInfo, fn)
      if (!heading) {
        textareaValRef.value = heading = `${getFileDocs()}${getFileImports()}`
      }
      if (typeof text == 'string' && text.length) {
        textareaValRef.value += `\n${text}`
      }
    }
    message.success('生成完成')
  } catch (error: any) {
    message.error(error.message || error)
  } finally {
    isGenCoding.value = false
  }
}
async function onCopyCodeBtnClick(
  record: R.IResponse<(typeof eolink)['getApiList']>['apiList'][number]
) {
  const res = await eolink.getApiInfo({
    apiID: `${record.apiID}`,
    groupID: `${record.groupID}`,
    shareCode: store.getters.shareCode,
    shareID: store.getters.shareID,
    shareToken: store.getters.shareToken,
    shareType: 'project',
  })

  const text = runtime(res.apiInfo)
  if (typeof text == 'string' && text.length) {
    await navigator.clipboard.writeText(text)
    message.success('拷贝成功')
  } else {
    message.warn(
      '当前接口配置规则返回为' + text + '，如果需要处理请修改配置文件'
    )
  }
}

function formatedJSON(record: Record<string, unknown>): string {
  var res = ''

  _.each(record, (v, k) => {
    if (res) {
      res += '<br />'
    }
    res += `${k}: ${v}`
  })

  return res
}
</script>

<template>
  <div class="wrapper">
    <a-page-header>
      <template #title>
        <a-tooltip title="点击配置模版">
          <router-link to="/eo/cfg"> API列表 </router-link>
        </a-tooltip>
      </template>
      <template #extra>
        <!-- 业务场景只会加载所有的api,先不做分页加载 -->
        <a-checkbox v-model:checked="isLoadAllRef" :disabled="true">
          加载全部
        </a-checkbox>
        <a-button
          type="link"
          @click="
            onGenCodeBtnClick(
              _.size(selectedIds)
                ? _.filter(data, (record) => selectedIds.has(record.apiID + ''))
                : (data as any[])
            )
          "
        >
          {{
            _.size(selectedIds)
              ? `生成选择项(${_.size(selectedIds)})`
              : '全部批量生成代码'
          }}
        </a-button>
      </template>
      <div class="input-box">
        <a-input
          v-model:value="inputValRef"
          placeholder="请输入查询keyword"
          size="large"
        ></a-input>
        <a-button :loading="reloading" size="large" @click="reload"
          >查询</a-button
        >
      </div>
    </a-page-header>
    <div class="wrapper__content">
      <a-list :data-source="data" :loading="loading">
        <template #renderItem="{ item }">
          <a-list-item>
            <a-list-item-meta>
              <template #title>
                <a-badge-ribbon v-bind="getApiStatusMap(item.apiStatus)">
                  <a-tag
                    v-if="item.apiRequestType == ApiRequestType.GET"
                    color="success"
                    >GET</a-tag
                  >
                  <a-tag
                    v-else-if="item.apiRequestType == ApiRequestType.POST"
                    color="processing"
                    >POST</a-tag
                  >
                  <a-tag
                    v-else-if="item.apiRequestType == ApiRequestType.PUT"
                    color="warning"
                    >PUT</a-tag
                  >
                  <a-tag
                    v-else-if="item.apiRequestType == ApiRequestType.DEL"
                    color="warning"
                    >DELETE</a-tag
                  >
                  <a-tag v-else color="default">{{
                    item.apiRequestType
                  }}</a-tag>
                  <a-tooltip>
                    <template #title>
                      <span v-html="formatedJSON(item)"></span>
                    </template>

                    <a-typography-text
                      type="secondary"
                      :copyable="item.apiURI"
                      underline
                    >
                      {{ `${item.apiURI}` }}
                      <br />
                      <a-checkbox
                        :checked="selectedIds.has(item.apiID + '')"
                        @update:checked="
                          $event
                            ? selectedIds.add(item.apiID + '')
                            : selectedIds.delete(item.apiID + '')
                        "
                      ></a-checkbox>
                      {{ `[${item.apiID}](${item.apiName})` }}
                    </a-typography-text>
                  </a-tooltip>
                </a-badge-ribbon>
              </template>
            </a-list-item-meta>
            <template #extra>
              <div>
                <a-button type="link" @click="onGenCodeBtnClick([item])"
                  >生成</a-button
                >
                <a-divider type="vertical" />
                <a-button type="link" @click="onCopyCodeBtnClick(item)"
                  >copy</a-button
                >
              </div>
            </template>
          </a-list-item>
        </template>
      </a-list>
      <a-textarea
        v-model:value="textareaValRef"
        placeholder="生成结果"
      ></a-textarea>
    </div>
  </div>
</template>

<style lang="less" scoped>
.wrapper {
  width: 80vw;

  .input-box {
    display: flex;
    text-align: left;
    align-items: center;
    gap: 1em;
  }

  &__content {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }

  .ant-list {
    max-height: 80vh;
    overflow: auto;
  }
}
</style>
